package herramientas;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Scanner;

/**
 * @author BIT COMPANY
 */
public class BitUtil {

    /**
     * Borra la pantalla escribiendo 50 líneas vacias
     */
    public static void borra() {
        for (int i = 0; i < 50; i++) {
            System.out.println("");
        }
    }

    
    /**
     * Pide una cadena a través del teclado y la devuelve
     * además se asegura de cambiar la comilla simple por un acento
     */
    public static String dameCadena(String mensaje) {
        String cadena;
        Scanner scan = new Scanner(System.in);

        System.out.print(mensaje);
        cadena = scan.nextLine();
        
        //Cambiamos la comilla simple por un acento para que no falle el SQL
        cadena=cadena.replace("'", "´");

        return cadena;
    }

    
    /**
     * Pide una cadena a través del teclado y la devuelve
     * Seguirá pidiendo la cadena hasta que tenga menos caracteres que maxCar
     */
    public static String dameCadena(String mensaje, int maxCar) {
        String cadena;
        boolean error;
        do {
            error = false;
            cadena = dameCadena(mensaje);
            if (cadena.length() > maxCar) {
                System.out.println("El texto es demasiado largo. Solo puede usar " + maxCar + " caracteres.");
                error = true;
            }
        } while (error);
        return cadena;
    }

    
    /**
     * Pide un número entero a través del teclado y lo devuelve.
     * Seguirá pidiendo el valor hasta que sea válido.
     */
    public static int dameEntero(String mensaje) {
        int numero = 0;
        String respuesta;
        boolean error;
        do {
            error = false;
            respuesta = dameCadena(mensaje);
            if (respuesta.length() == 0) {
                error = true;
            }
            try {
                numero = Integer.parseInt(respuesta);
            } catch (NumberFormatException a) {
                System.out.println("El valor introducido no es válido");
                error = true;
            }
        } while (error);
        return numero;
    }


    /**
     * Pide un número entero a través del teclado y lo devuelve.
     * Seguirá pidiendo el valor hasta que sea válido y mayor que cero.
     */
    public static int dameEnteroNoNegativo(String mensaje) {
        int numero = 0;
        String respuesta;
        boolean error;
        do {
            error = false;
            respuesta = dameCadena(mensaje);
            if (respuesta.length() == 0) {
                error = true;
            }
            try {
                numero = Integer.parseInt(respuesta);
                if (numero < 0) {
                    System.out.println("Debe ser positivo");
                    error = true;
                }
            } catch (NumberFormatException a) {
                System.out.println("El valor introducido no es válido");
                error = true;
            }
        } while (error);
        return numero;
    }

    
    /**
     * Pide un double a través del teclado y lo devuelve.
     * Seguirá pidiendo el valor hasta que sea válido.
     */
    public static double dameDouble(String mensaje) {
        double numero = 0;
        String respuesta;
        boolean error;
        do {
            error = false;
            respuesta = dameCadena(mensaje);
            if (respuesta.length() == 0) {
                error = true;
            }
            try {
                numero = Double.parseDouble(respuesta);
            } catch (NumberFormatException a) {
                System.out.println("El valor introducido no es válido");
                error = true;
            }
        } while (error);
        return numero;
    }

    
    /**
     * Pide un double a través del teclado y lo devuelve.
     * Seguirá pidiendo el valor hasta que sea válido y mayor que cero.
     */
    public static double dameDoubleNoNegativo(String mensaje) {
        double numero = 0;
        String respuesta;
        boolean error;
        do {
            error = false;
            respuesta = dameCadena(mensaje);
            if (respuesta.length() == 0) {
                error = true;
            }
            try {
                numero = Double.parseDouble(respuesta);
                if (numero < 0) {
                    System.out.println("Debe ser positivo");
                    error = true;
                }
            } catch (NumberFormatException a) {
                System.out.println("El valor introducido no es válido");
                error = true;
            }
        } while (error);
        return numero;
    }

    
    /**
     * Muestra un menú por pantalla y espera hasta que la opción seleccionada
     * sea válida. Mostrará todas las opciones que haya dentro del array que se
     * pasa como parámetro y además mostrará el 0 como la opción "0.- Salir"
     */
    public static int muestraMenu(String titulo, String[] opcion) {
        int respuesta;
        respuesta = muestraMenu(titulo, opcion, "Salir");
        return respuesta;
    }

    
    /**
     * Muestra un menú por pantalla y espera hasta que la opción seleccionada
     * sea válida. Recibe título, opciones[] y texto de salida. Se diferencia
     * de muestraMenu(String, String[]) en que se puede seleccionar el texto que
     * aparece en la opción de salir 0. Si se introduce una cadena vacía "" no
     * aparecerá la opción 0 y obligará a seleccionar una de las opciones.
     */
    public static int muestraMenu(String titulo, String[] opcion, String salir) {
        String respuestaString = "";
        int respuesta = 0;
        
        //Titulo del menú
        System.out.println(muestraSubrayado(titulo, "-"));
        
        //Opciones del menú
        for (int i = 0; i < opcion.length; i++) {
            if (i < 9) {
                System.out.print(" ");
            }
            System.out.print((i + 1) + ".- " + opcion[i] + "\n");
            //Si hay muuuchas opciones hacemos una pausa cada 15 elementos de la lista
            if ((i + 1) % 15 == 0) {
                BitUtil.esperaEnter();
                BitUtil.borra();
                System.out.println(muestraSubrayado(titulo, "-"));
            }
        }
        
        //Si el salir es una cadena vacía no se muestra la opcion "0.-salir"
        if(!salir.equals("")){
            System.out.println(" 0.- " + salir + "\n");
        } else {
            System.out.println(""); //Linea en blanco
        }
        
        boolean error = false;
        do {
            //Detectamos el error por no introducir un número
            try {
                error = false;
                System.out.print("Opcion: ");
                Scanner scan = new Scanner(System.in);
                respuestaString = scan.nextLine();
                respuesta = Integer.parseInt(respuestaString);
            } catch (NumberFormatException excep) {
                System.out.println("Introduzca solamente números, por favor");
                error = true;
            }

            //Detectamos el error por ser un número fuera de las opciones
            if (respuesta < 0 || respuesta > opcion.length) {
                System.out.println("La opcion solicitada no existe");
                error = true;
            }
            
            //Detectamos el error por seleccionar "salir" cuando no se puede
            if(respuesta==0 && salir.equals("")){
                System.out.println("Debe seleccionar alguna opcion");
                error = true;
            }
        } while (error);

        return respuesta;
    }

    
    /**
     * Muestra un texto pidiendo que se pulse Enter...
     */
    public static void esperaEnter() {
        System.out.print("Pulse Enter para continuar...");
        try {
            System.in.read();
        } catch (Exception e) {
        }
    }

    
    /**
     * Pide confirmación por pantalla con (S/N) y devuelve un boolean.
     * Seguirá pidiendo el valor hasta que sea válido. S/s:True o N/n:False
     */
    public static boolean dameConfirmacion(String mensaje) {
        boolean siONo = false;
        String respuesta;
        boolean error;
        do {
            error = true;
            respuesta = dameCadena(mensaje);
            if (respuesta.equals("s") || respuesta.equals("S")) {
                siONo = true;
                error = false;
            }
            if (respuesta.equals("n") || respuesta.equals("N")) {
                siONo = false;
                error = false;
            }
        } while (error);
        return siONo;
    }

    
    /**
     * Pide una fecha por pantalla con el formato "dd/mm/yyyy" y devuelve un Date
     * seguirá pidiendo la fecha hasta que sea una fecha válida
     */
    public static Date dameFecha(String mensaje) {
        String cadena = "";
        Date fecha = null;
        DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

        boolean error;

        do {
            error = false;
            try {
                //Pedimos la fecha
                cadena = dameCadena(mensaje, 10);
                if (cadena.length() == 0) {
                    return null;
                }
                //La intentamos parsear y no se puede, lanza la exception
                fecha = dateFormat.parse(cadena);
                //Cogemos por separado el año, mes y día
                String[] parte = cadena.split("/");
                int ano = Integer.parseInt(parte[2]);
                int mes = Integer.parseInt(parte[1]);
                int dia = Integer.parseInt(parte[0]);
                //Creamos un calendario Gregoriano del mes y año introducidos
                Calendar calendario = new GregorianCalendar(ano, mes - 1, 1);
                //Vemos cuantos días tenía ese mes en dicho año (podría ser bisiesto)
                int diaMax = calendario.getActualMaximum(Calendar.DAY_OF_MONTH);
                //Comprobamos que la fecha es válida
                if (ano < 1887 || mes > 12 || mes < 1 || dia > diaMax || dia < 1) {
                    //En 1887 se hizo la animación del caballo galopando por medio de fotografías
                    error = true;
                }
            } catch (Exception ex) {
                error = true;
            }
            //Si hubo algún error, mostramos el cartel y repetimos todo
            if (error) {
                System.out.println("Formato de fecha no valido (dia/Mes/año)");
            }

        } while (error);

        return fecha;
    }

    
    /**
     * Pide un entero con un número fijo de caracteres a través del teclado y lo devuelve.
     * Seguirá pidiendo el valor hasta que sea válido.
     */
    public static String dameEnteroFijo(String mensaje, int numCar) {
        long numero = 0;
        String respuesta = null;
        boolean error;
        do {
            error = false;
            respuesta = dameCadena(mensaje);
            if (respuesta.length() == 0) {
                return "";
            }
            if (respuesta.length() != numCar) {
                System.out.println("El número de cifras no es correcto");
                error = true;
            }
            try {
                numero = Integer.parseInt(respuesta);
            } catch (NumberFormatException a) {
                System.out.println("El valor introducido no es válido");
                error = true;
            }
        } while (error);
        return respuesta;
    }

    
    /**
     * Pide un dia de la semana, basta con la primera letra excepto para martes
     * y miércoles que mira las dos primeras. Devuelve un string con el nombre del día completo
     */
    public static String dameDiaSemana(String mensaje) {
        String dia;

        boolean error;
        do {
            error = true;
            dia = dameCadena(mensaje);

            if (dia.startsWith("l") || dia.contains("L")) {
                error = false;
                dia = "lunes";
            }
            if (dia.startsWith("ma") || dia.contains("Ma")) {
                error = false;
                dia = "martes";
            }
            if (dia.startsWith("mi") || dia.contains("Mi")) {
                error = false;
                dia = "miercoles";
            }
            if (dia.startsWith("j") || dia.contains("J")) {
                error = false;
                dia = "jueves";
            }
            if (dia.startsWith("v") || dia.contains("V")) {
                error = false;
                dia = "viernes";
            }
            if (dia.startsWith("s") || dia.contains("S")) {
                error = false;
                dia = "sabado";
            }
            if (dia.startsWith("d") || dia.contains("D")) {
                error = false;
                dia = "domingo";
            }

            if (error) {
                System.out.println("Introduzca un día de la semana valido");
            }

        } while (error);
        return dia;
    }

    
    /**
     * Devuelve un String con la fecha en formato 'bonito y español'
     */
    public static String muestraFecha(Date fecha) {
        String[] nombreMes = new String[]{"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"};
        String fechaString;
        Calendar cal = new GregorianCalendar();
        cal.setTime(fecha);
        String dia = Integer.toString(cal.get(Calendar.DAY_OF_MONTH));
        String mes = nombreMes[cal.get(Calendar.MONTH)];
        String año = Integer.toString(cal.get(Calendar.YEAR));
        fechaString = dia + "/" + mes + "/" + año;
        return fechaString;
    }


    /**
     * Pinta el logo de Bit Company
     */
    public static void logo() {
        System.out.println("           __________________________ ");
        System.out.println("                                      ");
        System.out.println("             ######         ######    ");
        System.out.println("             ##    #       ###    #   ");
        System.out.println("             ######        ##         ");
        System.out.println("             ##   ##       ##         ");
        System.out.println("             ##    ##      ###    #   ");
        System.out.println("             #######        ######    ");
        System.out.println("           __________________________ ");
        System.out.println("                   Bit Company        ");
        System.out.println("           __________________________ ");
        System.out.println("");
        System.out.println("");
        System.out.println("");
    }

    
    /**
     * Pide el sexo de una persona por pantalla, según el criterio hombre/mujer
     * Seguirá pidiendo el valor hasta que sea válido. H/h:hombre o M/m:mujer
     */
    public static char dameSexo(String mensaje) {
        char hombreOMujer = ' ';
        String respuesta;
        boolean error;
        do {
            error = false;
            respuesta = dameCadena(mensaje);
            if (respuesta.length() > 0) {
                respuesta = respuesta.toLowerCase();
                hombreOMujer = respuesta.charAt(0);
                if (hombreOMujer != 'h' && hombreOMujer != 'm') {
                    error = true;
                }
            } else {
                error = true;
            }
        } while (error);
        return hombreOMujer;
    }

    
    /**
     * Devuelve un String compuesto de números que tiene el tamaño indicado
     * mientras el valor introducido no cumpla con el número de cifras seguirá pidiendo
     * Además si se pulsa enter (Cadena vacía) volverá a pedirlo también.
     */
    public static String dameEnteroFijoNoVacio(String mensaje, int numCar) {
        String respuesta = null;
        do {
            respuesta = dameEnteroFijo(mensaje, numCar);
            if (respuesta.length() == 0) {
                System.out.println("Este valor es obligatorio");
            }
        } while (respuesta.length() == 0);
        return respuesta;
    }


    /**
     * Devuelve un String que tiene el tamaño indicado mientras el valor
     * introducido no cumpla con el número de cifras seguirá pidiendo
     * Además si se pulsa enter (Cadena vacía) volverá a pedirlo también.
     */
    public static String dameCadenaNoVacio(String mensaje, int maxCar) {
        String respuesta = null;
        do {
            respuesta = dameCadena(mensaje, maxCar);
            if (respuesta.length() == 0) {
                System.out.println("Este valor es obligatorio");
            }
        } while (respuesta.length() == 0);
        return respuesta;
    }


    /**
     * Pide una fecha por pantalla con el formato "dd/mm/yyyy" y devuelve un Date
     * seguirá pidiendo la fecha hasta que sea una fecha válida
     * Además si se pulsa enter (Cadena vacía) volverá a pedirlo también.
     */
    public static Date dameFechaNoVacio(String mensaje) {
        Date respuesta = null;
        do {
            respuesta = dameFecha(mensaje);
            if (respuesta == null) {
                System.out.println("Este valor es obligatorio");
            }
        } while (respuesta == null);
        return respuesta;
    }

    
    /**
     * Devuelve un String con un número double puesto en formato moneda 0.00€
     */
    public static String muestraEuros(double dinero) {
        String stringDinero;
        int entero = (int) (dinero * 100);
        //System.out.printf ("%0.2f", dinero);
        if(entero%100<10){
            stringDinero = "" + (entero / 100) + ".0" + (entero % 100) + "€";
        }else{
            stringDinero = "" + (entero / 100) + "." + (entero % 100) + "€";
        }
        return stringDinero;
    }

    
    /**
     * Se le pasa una cadena y después de contar el número de caracteres que la
     * forman, añadirá un \n y dicho número de veces repetido un cierto carácter
     * El resultado es que devuelve la cadena lista para aparecer subrayada.
     */
    public static String muestraSubrayado(String mensaje, String tipo) {
        String mensajeSubrayado = mensaje + "\n";
        for (int i = 0; i < mensaje.length(); i++) {
            mensajeSubrayado += tipo;
        }
        return mensajeSubrayado;
    }
}
